/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "lwip/sockets.h"
#include "wifi_connect.h"

#include "wifiiot_errno.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_adc.h"
#include "wifiiot_uart.h"
#include "wifiiot_pwm.h"
#include "hi_io.h"
#include "hi_uart.h"
#include "hi_gpio.h"
#include "hi_time.h"
#include "hi_i2c.h"
#include "max30102_hello.h"
#include "ultrasonic_module.h"
#include "wifiiot_i2c.h"
#include "wifiiot_i2c_ex.h"

#include <math.h>

#define UART_BUFF_SIZE 1000
#define PEN_SIZE 20
#define TEMP_SIZE 4	  // 36.5
#define HEIGHT_SIZE 5 // 178.0
#define HEART_SIZE 4  // 66.0

#define READ_TIME 100

#define _PROT_ 8888
#define TCP_BACKLOG 10

#define BLUE_RX_5 5
#define BLUE_TX_6 6

enum pullRequest
{
	HEIGHT = 'h',
	TEMPERATURE = 'w',
	HEART = 'x',
	POWER = 'b',
};

// 在sock_fd 进行监听，在 new_fd 接收新的链接
int sock_fd, new_fd;
char nullstr = '0';
unsigned char recvbuf[512];
char buf[PEN_SIZE] = {0};
char *teststr = "17535.66299";// 数据帧样例
#define DTA_LEN 11
char *ah_heart = "0000000"; // heart前补齐7位字符
char *ah_temp = "000";		// temp前补齐3位字符
float wendu = 0.0;
static const char cmd_temp[] = {0xAA, 0xA5, 0x03, 0x01, 0x04, 0x55}; // 获取B-1传感温度指令
// 返回参数 9字节 0xAA 0xA5 08 01 02 [01 34 ] 01 29 55； 
// 其中01 34 体温计算为 = (4+16*3+1*16*16)/10 = 308 /10 =30.8℃
#define TEMP_CMD_LEN 6
#define READ_TEMP_LEN 10

float height = 0.0;
char height_buff[HEIGHT_SIZE] = {0};

unsigned short IR_channel_data = 0;	 // 脉搏
unsigned short RED_channel_data = 0; // 血氧
char IR_buff[HEART_SIZE] = {0};
char RED_buff[HEART_SIZE] = {0};

void Float2String(float src, char *desString, unsigned int mplace)
{
	float ftem = 0;
	unsigned int iplace = 1;
	unsigned int i = 0;
	if (src >= 0)
	{
		ftem = src;
	}
	else
	{
		ftem = -src;
	}

	if (ftem >= 10.0)
	{
		while (ftem >= 10.0)
		{
			iplace++;
			ftem /= 10;
		}
	}
	if (src < 0)
	{
		desString[0] = '-'; //
		i = 1;
		iplace++;
	}

	for (; i < iplace + mplace + 1; i++)
	{
		if (i == iplace)
		{
			if (mplace)
			{
				desString[i] = '.';
				continue;
			}
			else
				break;
		}
		else
		{
			desString[i] = (unsigned int)ftem;
			ftem -= desString[i];
			desString[i] += '0'; // 数值转换为字符 0x30 = '0'
			ftem *= 10;
		}
	}
}
static void getHeart(void)
{
	strcpy(buf, ah_heart);
	float heart_temp = 0.0;
	// 获取心率
	max_Data(&RED_channel_data, &IR_channel_data);
	printf("RED: %d, IR: %d\n", RED_channel_data, IR_channel_data);
	// RED_channel_data =  88.0;
	heart_temp = (float)(RED_channel_data / 1000.0);
	Float2String(2 * heart_temp, RED_buff, 0);
	// IR_channel_data = 99;
	heart_temp = (float)(IR_channel_data / 91.0);
	Float2String(heart_temp, IR_buff, 0);
	printf("RED_buff: %s\n", RED_buff);
	printf("IR_buff: %s\n", IR_buff);
	strcat(buf, RED_buff);
	strcat(buf, IR_buff);
	return;
}

static void getHeight(void)
{
	// 获取高度
	// height = get_distance();
	printf("height = %lf\n", height);
	// height = 172.7;
	Float2String(height, height_buff, 1);
	printf("height_buff: %s\n", height_buff);
	strcpy(buf, height_buff);
	return;
}

static void getTemp(void)
{
   // 另一个线程测量温度，浮点数转换为字符串，换成到tcp buf中
	char temp_buff[TEMP_SIZE] = {0};
	strcpy(buf, ah_temp);
	Float2String(wendu, temp_buff, 1);
	printf("temp_buff: %s\n", temp_buff);
	strcat(buf, temp_buff);
	return;
}

static void TCPServerTask(void)
{
	GpioInit();
	hi_io_set_func(MAX_SDA_IO0, HI_IO_FUNC_GPIO_0_I2C1_SDA);
	hi_io_set_func(MAX_SCL_IO1, HI_IO_FUNC_GPIO_1_I2C1_SCL);
	hi_i2c_init(MAX_I2C_IDX, MAX_I2C_BAUDRATE);
	max_init();

	// 服务端地址信息
	struct sockaddr_in server_sock;

	// 客户端地址信息
	struct sockaddr_in client_sock;
	int sin_size;

	struct sockaddr_in *cli_addr;

	// 连接Wifi
	WifiConnect("r1", "88888889");

	// 创建socket
	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket is error\r\n");
		exit(1);
	}

	bzero(&server_sock, sizeof(server_sock));
	server_sock.sin_family = AF_INET;
	server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	server_sock.sin_port = htons(_PROT_);

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
	{
		perror("bind is error\r\n");
		exit(1);
	}

	//调用listen函数监听(指定port监听)
	if (listen(sock_fd, TCP_BACKLOG) == -1)
	{
		perror("listen is error\r\n");
		exit(1);
	}

	printf("start accept\n");

	//调用accept函数从队列中
	while (1)
	{

		sin_size = sizeof(struct sockaddr_in);

		if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
		{
			perror("accept");
			continue;
		}

		cli_addr = malloc(sizeof(struct sockaddr));

		printf("accept addr\r\n");

		if (cli_addr != NULL)
		{
			memcpy(cli_addr, &client_sock, sizeof(struct sockaddr));
		}

		//处理目标
		ssize_t ret;
		unsigned char msg_cmd = '0';
		uint8_t uart_buff[UART_BUFF_SIZE] = {0};
		uint8_t *uart_buff_ptr = uart_buff;
		while (1)
		{

			if ((ret = recv(new_fd, recvbuf, sizeof(recvbuf), 0)) == -1)
			{
				printf("recv error \r\n");
			}
			printf("recv :%s\r\n", recvbuf);
			msg_cmd = recvbuf[0];
			printf("msg_cmd: %c\n", msg_cmd);
			switch (msg_cmd)
			{
			case HEIGHT:
			{
				getHeight();
				break;
			}
			case TEMPERATURE:
			{
				getTemp();
				break;
			}
			case HEART:
			{
				getHeart();
				break;
			}
			default:
				break;
			}
			printf("buf= %s \n", buf);

			if ((ret = send(new_fd, &buf, strlen(buf) + 1, 0)) == -1)
			{
				perror("send : ");
			}
			strcpy(buf, &nullstr);
		}

		close(new_fd);
	}
}

static void TCPServerDemo(void)
{
	osThreadAttr_t attr;

	attr.name = "TCPServerTask";
	attr.attr_bits = 0U;
	attr.cb_mem = NULL;
	attr.cb_size = 0U;
	attr.stack_mem = NULL;
	attr.stack_size = 10240;
	attr.priority = osPriorityNormal;

	if (osThreadNew((osThreadFunc_t)TCPServerTask, NULL, &attr) == NULL)
	{
		printf("[TCPServerDemo] Falied to create TCPServerTask!\n");
	}
}

APP_FEATURE_INIT(TCPServerDemo);


#define UART_TASK_STACK_SIZE 1024 * 8
#define UART_TASK_PRIO 25
#define UART_BUFF_SIZE 1000

static const char data[] = {0xAA, 0xA5, 0x03, 0x01, 0x04, 0x55};

static void UART_Task(void)
{
    uint8_t uart_buff[UART_BUFF_SIZE] = {0};
    uint8_t *uart_buff_ptr = uart_buff;
    uint32_t ret;

    WifiIotUartAttribute uart_attr = {

        // baud_rate: 9600
        .baudRate = 38400,

        // data_bits: 8bits
        .dataBits = 8,
        .stopBits = 1,
        .parity = 0,
    };

    // Initialize uart driver
    ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL); // GPIO5-RX、GPIO6-TX
    if (ret != WIFI_IOT_SUCCESS)
    {
        printf("Failed to init uart! Err code = %d\n", ret);
        return;
    }
    printf("UART Test Start\n");
    int temp[] = {0, 0, 0};
    // float wendu = 0;
    while (1)
    {

        //通过串口1发送数据
        UartWrite(WIFI_IOT_UART_IDX_1, (unsigned char *)data, strlen(data));

        //通过串口1接收数据
        UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE);
        temp[0] = uart_buff[5] * 16 * 16;
        temp[1] = ((uart_buff[6] & 0xF0)>>4) * 16;
        temp[2] = (uart_buff[6] & 0x0F);
        // printf("temp[0-2]%d ", temp[0]);
        // printf("%d ", temp[1]);
        // printf("%d\n", temp[2]);
        wendu = (float)( (float)(temp[0]+temp[1]+temp[2])/10.0);
        printf("wendu = %.2f\n",wendu);
        // printf("%c", uart_buff[5]);
        // printf("%c\n", uart_buff[6]);
        // printf("%s", uart_buff_ptr);

		height = get_distance();

        usleep(1000000);
    }
}

static void UART_ExampleEntry(void)
{

    osThreadAttr_t attr;

    attr.name = "UART_Task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = UART_TASK_STACK_SIZE;
    attr.priority = UART_TASK_PRIO;

    if (osThreadNew((osThreadFunc_t)UART_Task, NULL, &attr) == NULL)
    {
        printf("[ADCExample] Falied to create UART_Task!\n");
    }
}

APP_FEATURE_INIT(UART_ExampleEntry);